package com.common.util;

import com.bean.LambdaResolve;
import com.bean.PropertyFunction;
import lombok.extern.slf4j.Slf4j;

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;

/**
 * Common enum util
 *
 * @description: 枚举工具类
 * @author: cyj
 * @date 2022 -07-29 14:24:36
 */
@Slf4j
public class CommonEnumUtil {

    /**
     * Gets enum * 根据 equal获取枚举
     * code 类型与 eqPropertyMethod方法返回值 必须一致，基本类型使用包装类！！！！！！！！
     * show GlobalDefaultEnum anEnum = CommonEnumUtil.getEnum("1.0.0000", GlobalDefaultEnum::message, GlobalDefaultEnum.class);
     * show GlobalDefaultEnum anEnum = CommonEnumUtil.getEnum(1, GlobalDefaultEnum::getCode, GlobalDefaultEnum.class);
     * @param <T>              parameter  枚举类型
     * @param <P>              parameter code字段类型
     * @param code             code 比较值A
     * @param eqPropertyMethod eq property method 根据这个枚举方法获取比较值B， 这个方法必须enumClass的方法
     * @param enumClass        enum class 枚举
     * @return the enum
     */
    public static <T, P> T getEnum(P code, PropertyFunction<T, ?> eqPropertyMethod, Class<T> enumClass) {
        if (!enumClass.isEnum()) {
            log.warn("enumClass 不是枚举类型");
            return null;
        }

        T[] enumConstants = enumClass.getEnumConstants();

        String methodName = LambdaResolve.getMethodName(eqPropertyMethod);

        T returnEnum = null;
        for (T enumObj:
             enumConstants) {
            Class<?> aClass = enumObj.getClass();
            Method method = null;
            try {
                method = aClass.getMethod(methodName);
            } catch (NoSuchMethodException e) {
                log.warn("枚举没有eqProperty方法：{}", e);
                return returnEnum;
            }
            Class<?> returnType = method.getReturnType();
            if (!returnType.getTypeName().equals(code.getClass().getTypeName())) {
                log.warn("code 类型与 eqPropertyMethod方法返回值不一致, {}, {}", returnType.getTypeName(), code.getClass().getTypeName());
                return returnEnum;
            }
            try {
                P value = (P) method.invoke(enumObj);
                if (value.equals(code)) {
                    returnEnum = enumObj;
                    break;
                }
            } catch (IllegalAccessException | InvocationTargetException e) {
                log.warn("用eqProperty返回值比较code失败：{}", e);
            }
        }
        return returnEnum;
    }

}
